package com.dave.weixin.common.nio.selector;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;

/**
 * Created by Dave on 2018/7/11
 * Describes   selector 选择器
 */
public class SelectorTest {

    ///////////////////////////////////////////////////////////////////////////
    // Selector（选择器）是Java NIO中能够检测一到多个NIO通道，
    // 并能够知晓通道是否为诸如读写事件做好准备的组件。
    // 这样，一个单独的线程可以管理多个channel，从而管理多个网络连接。
    // 单个线程处理多个通道的好处：减少线程资源的消耗。避免上行文的切换。
    ///////////////////////////////////////////////////////////////////////////


    public static void main(String[] args) throws IOException {

        //获得socket通道
        SocketChannel socketChannel = SocketChannel.open();
        //创建连接
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 8080));

        //创建selector
        Selector selector = Selector.open();

        //切换到非阻塞模式 与Selector一起使用时，Channel必须处于非阻塞模式下。这意味着不能将FileChannel与Selector一起使用，因为FileChannel不能切换到非阻塞模式。而套接字通道都可以。
        socketChannel.configureBlocking(false);


        //向selector注册通道 第二参数表示selector监听的事件类型
        //有四个类型：connect accept read write
        //可以同时监听多个使用 SelectionKey.OP_READ|SelectionKey.OP_ACCEPT
        SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);

        //注册的事件集合
        int ops = selectionKey.interestOps();

        //用“位与”操作interest 集合和给定的SelectionKey常量，可以确定某个确定的事件是否在interest 集合中
        boolean isInterestedInAccept = (ops & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;


        //ready集合:是通道已经准备就绪的操作的集合
        int readyOps = selectionKey.readyOps();
        //某个事件是否已经就绪
        boolean isAcceptReady = selectionKey.isAcceptable();


        //从SelectionKey访问Channel和Selector
        SelectableChannel channel = selectionKey.channel();
        Selector selector1 = selectionKey.selector();

        //附加对象：可以将一个对象或者更多信息附着到SelectionKey上，这样就能方便的识别某个给定的通道
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //附加对象
        selectionKey.attach(buffer);
        //得到附加对象
        Object attachment = selectionKey.attachment();
        //注册的时候也可以附加
        SelectionKey attachKey = socketChannel.register(selector, SelectionKey.OP_READ, buffer);



    }


}
